package com.dkts.oil.util;


import java.awt.geom.Point2D;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.List;

/**
 * @author heguanglong
 */
public class TrackMileageUtil {
    /**
     * 地球半径：6378137米
     */
    public static double EARTH_RADIUS = 6378137;

    /**
     * 地球的曲面
     */
    private static double spherical = 420;
    /**
     * 球开始曲面
     */
    private static double sphericalStart = 300;

    public static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    public static double rad() {
        return Math.PI / 180.0;
    }

    private static double degreesPerRadian = 180.0 / Math.PI;

    private static double metersPerDegree = 2.0 * Math.PI * EARTH_RADIUS / 360.0;

    /**
     * @param r  半径
     * return minLon,minLat,maxLon,maxLat
     */
    public static double[] getAround(double lon,double lat,double r){
        Double latitude = lat;
        Double longitude = lon;
        Double degree = (24901*1609)/360.0;
        Double dpmLat = 1/degree;
        Double radiusLat = dpmLat*r;
        Double minLat = latitude - radiusLat;
        Double maxLat = latitude + radiusLat;
        Double mpdLng = degree*Math.cos(latitude * (Math.PI/180));
        Double dpmLng = 1 / mpdLng;
        Double radiusLng = dpmLng*r;
        Double minLon = longitude - radiusLng;
        Double maxLon = longitude + radiusLng;
        return new double[]{minLon,minLat,maxLon,maxLat};
    }

    /**
     * 角度
     *
     * @param p1
     * @param p2
     * @param p3
     * @return
     */
    public static double angle(double[] p1, double[] p2, double[] p3) {
        double bearing21 = bearing(p2, p1);
        double bearing23 = bearing(p2, p3);
        double angle = bearing21 - bearing23;
        if (angle < 0.0) {
            angle += 360.0;
        }
        return angle;
    }

    /***
     * 平面多边形面积
     *
     * @param points
     * @return
     * */
    public static double getAreaByXy(List<Point2D.Double> points) {
        double a = 0.0;
        if (points.size() > 2) {
            for (int i = 0; i < points.size(); ++i) {
                int j = (i + 1) % points.size();
                double xi = points.get(i).x * metersPerDegree
                        * Math.cos(points.get(i).y * rad());
                double yi = points.get(i).y * metersPerDegree;
                double xj = points.get(j).x * metersPerDegree
                        * Math.cos(points.get(j).y * rad());
                double yj = points.get(j).y * metersPerDegree;
                a += xi * yj - xj * yi;
            }
        }
        a = BigDecimal.valueOf(Math.abs(a / 2.0)).setScale(1, BigDecimal.ROUND_DOWN).doubleValue();
        return a;
    }

    /**
     * 球面多边形面积计算
     *
     * @param points
     * @return
     */
    public static double sphericalPolygonAreaMeters2(List<double[]> points) {
        double totalAngle = 0.0;
        for (int i = 0; i < points.size(); i++) {
            int j = (i + 1) % points.size();
            int k = (i + 2) % points.size();
            totalAngle += angle(points.get(i), points.get(j), points.get(k));
        }

        double planarTotalAngle = (points.size() - 2) * 180.0;
        double sphericalExcess = totalAngle - planarTotalAngle;

        if (sphericalExcess > spherical) {
            totalAngle = points.size() * 360.0 - totalAngle;
            sphericalExcess = totalAngle - planarTotalAngle;
        } else if (sphericalExcess > sphericalStart && sphericalExcess < spherical) {
            sphericalExcess = Math.abs(360.0 - sphericalExcess);
        }
        return sphericalExcess * rad() * EARTH_RADIUS * EARTH_RADIUS;
    }

    /**
     * 计算经纬度的反向
     *
     * @param from
     * @param to
     * @return
     */
    public static double bearing(double[] from, double[] to) {
        double lat1 = from[1] * rad();
        double lon1 = from[0] * rad();
        double lat2 = to[1] * rad();
        double lon2 = to[0] * rad();
        double angle = -Math.atan2(
                Math.sin(lon1 - lon2) * Math.cos(lat2),
                Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
                        * Math.cos(lat2) * Math.cos(lon1 - lon2));
        if (angle < 0.0) {
            angle += Math.PI * 2.0;
        }
        angle = angle * degreesPerRadian;
        return angle;
    }


    /**
     * 计算两点间的距离 -米
     *
     * @return
     */
    public static double distance(double sourceLat, double sourceLon, double targetLat, double targetLon) {
        double radLat1 = rad(sourceLat);
        double radLat2 = rad(targetLat);
        double a = radLat1 - radLat2;
        double b = rad(sourceLon) - rad(targetLon);
        double s = 2 * Math.asin(
                Math.sqrt(
                        Math.pow(
                                Math.sin(a / 2), 2
                        )

                                + Math.cos(radLat1) * Math.cos(radLat2)
                                *
                                Math.pow(
                                        Math.sin(b / 2), 2
                                )
                )
        );
        //弧长乘地球半径（半径为米）
        s = s * EARTH_RADIUS;
        s = Math.round(s * 10000d) / 10000d;
        DecimalFormat df = new DecimalFormat("#.000");
        return Double.valueOf(df.format(s));
    }



    /**
     * 计算两点间的距离 -米
     *
     * @param distance
     * @return
     */
    public static double getDistanceHeight(double distance, double height) {
        double d = distance * distance + height * height;
        d = Math.pow(d, 2);
        DecimalFormat df = new DecimalFormat("#.000");
        return Double.valueOf(df.format(d));
    }






    public static BigDecimal  countTime(Date endTime,Date start){
        if (endTime == null || start == null) {
            return new BigDecimal(0);
        }
        return new BigDecimal(endTime.getTime() - start.getTime());
    }



    /**
     *  
     * 基于余弦定理求两经纬度距离 
     *
     * @param lon1 第一点的精度 
     * @param lat1 第一点的纬度 
     * @param z1   第二点的精度 
     * @param lon2 第二点的纬度 
     * @param lat2 第二点的精度 
     * @param z2   第二点的纬度 
     * @return 返回的距离，单位km
     *      *
     */
    public static double lantitudeLongitudeDist(double lon1, double lat1, double z1, double lon2, double lat2, double z2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double radLon1 = rad(lon1);
        double radLon2 = rad(lon2);
        /**south*/
        if (radLat1 < 0) {
            radLat1 = Math.PI / 2 + Math.abs(radLat1);
        }
        /**north*/
        if (radLat1 > 0) {
            radLat1 = Math.PI / 2 - Math.abs(radLat1);
        }
        /**west*/
        if (radLon1 < 0) {
            radLon1 = Math.PI * 2 - Math.abs(radLon1);
        }
        /**south*/
        if (radLat2 < 0) {
            radLat2 = Math.PI / 2 + Math.abs(radLat2);
        }
        /**north*/
        if (radLat2 > 0) {
            radLat2 = Math.PI / 2 - Math.abs(radLat2);
        }
        /** west  */
        if (radLon2 < 0) {
            radLon2 = Math.PI * 2 - Math.abs(radLon2);
        }
        double x1 = EARTH_RADIUS * Math.cos(radLon1) * Math.sin(radLat1);
        double y1 = EARTH_RADIUS * Math.sin(radLon1) * Math.sin(radLat1);

        double x2 = EARTH_RADIUS * Math.cos(radLon2) * Math.sin(radLat2);
        double y2 = EARTH_RADIUS * Math.sin(radLon2) * Math.sin(radLat2);
        double d = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) + (z1 - z2) * (z1 - z2));
        double theta = Math.acos((EARTH_RADIUS * EARTH_RADIUS + EARTH_RADIUS * EARTH_RADIUS - d * d) / (2 * EARTH_RADIUS * EARTH_RADIUS));
        double dist = theta * EARTH_RADIUS;
        return dist;
    }



    public static String getTrackId(String deviceId){
        return "lk-"+deviceId;
    }
}
